import {
  ReactiveEffect,
  trackEffect,
  triggerEffect,
  isTracking,
} from "./effect";
import { ReactiveFlags, toRaw, isProxy, reactive } from "./reactive";
import { isObject, hasChanged } from "../utils/index";
import { createDep } from "./dep";
export function ref(value: any) {
  if (isRef(value)) {
    return value;
  }
  return new RefImpl(value);
}

export function isRef(value: any) {
  return !!value[ReactiveFlags.IS_REF];
}

class RefImpl {
  private _value;
  private _rawValue;

  public dep;

  public readonly __v_isRef = true;

  constructor(value: any) {
    // 需要将数据变成响应式数据
    this._value = isObject(value) ? reactive(value) : value;
    // 保存为原始值
    this._rawValue = isProxy(value) ? toRaw(value) : value;

    this.dep = createDep();
  }

  get __v_raw() {
    return this._rawValue;
  }

  set value(v) {
    if (hasChanged(v, this._rawValue)) {
      const oldValue = this._rawValue;
      // 需要将数据再次变成响应式数据
      // 这里其实相当于是对基本数据的代理
      this._value = isObject(v) ? reactive(v) : v;
      this._rawValue = isProxy(v) ? toRaw(v) : v;
      triggerRefValue(this, v, oldValue);
    }
  }
  get value() {
    trackRefValue(this);
    return this._value;
  }
}

export function trackRefValue(target) {
  if (isTracking()) {
    trackEffect(target.dep);
  }
}

export function triggerRefValue(target, newValue, oldValue) {
  triggerEffect(target.dep);
}
